"""View base classes

All views are event handlers, some may be game states"""

import pyglet
from pyglet.gl import *
import window


class ScrollingView(object):
	"""A view larger than the viewport"""

	SCROLL_KEY_SPEED = 1
	WIDTH = HEIGHT = None

	scroll_x = scroll_y = scroll_dx = scroll_dy = 0

	def on_key_press(self, symbol, modifiers):
		if not modifiers:
			if symbol == pyglet.window.key.LEFT:
				self.scroll_dx = -self.SCROLL_KEY_SPEED
				return pyglet.event.EVENT_HANDLED
			elif symbol == pyglet.window.key.RIGHT:
				self.scroll_dx = self.SCROLL_KEY_SPEED
				return pyglet.event.EVENT_HANDLED
			elif symbol == pyglet.window.key.UP:
				self.scroll_dy = self.SCROLL_KEY_SPEED
				return pyglet.event.EVENT_HANDLED
			elif symbol == pyglet.window.key.DOWN:
				self.scroll_dy = -self.SCROLL_KEY_SPEED
				return pyglet.event.EVENT_HANDLED
	
	def on_key_release(self, symbol, modifiers):
		if symbol in (pyglet.window.key.LEFT, pyglet.window.key.RIGHT):
			self.scroll_dx = 0
			return pyglet.event.EVENT_HANDLED
		elif symbol in (pyglet.window.key.UP, pyglet.window.key.DOWN):
			self.scroll_dy = 0
			return pyglet.event.EVENT_HANDLED
	
	def translate_view(self, scaling=1.0):
		"""Translate the view according to the current scroll position"""
		glTranslatef(-self.scroll_x*scaling, -self.scroll_y*scaling, 0)

	def on_update(self, dt):
		self.scroll_x += self.scroll_dx * dt
		self.scroll_y += self.scroll_dy * dt
		if self.HEIGHT is not None:
			limit = self.HEIGHT // 2
			self.scroll_y = min(limit, max(-limit, self.scroll_y))
		if self.WIDTH is not None:
			limit = self.WIDTH // 2
			self.scroll_x = min(limit, max(-limit, self.scroll_x))


class Wireframe(object):
	"""Renders a model using a wireframe view"""

	SHADED_COLOR_SCALE = 0.5
	EDGE_GLOW_WIDTH = 5
	EDGE_GLOW_ALPHA = 0.07
	BACK_EDGE_WIDTH = 2

	def __init__(self, model, color=(1,1,1)):
		self.model = model
		self.color = color
		r, g, b = self.color
		self.shade_color = (r * self.SHADED_COLOR_SCALE, 
			g * self.SHADED_COLOR_SCALE, 
			b * self.SHADED_COLOR_SCALE)
	
	def draw(self):
		glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_POLYGON_BIT)
		# Shaded Fill
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
		glEnable(GL_LIGHTING)
		glEnable(GL_CULL_FACE)
		glEnable(GL_DEPTH_TEST)
		r, g, b = self.color
		glColor3f(*self.shade_color)
		self.model.draw()
		# Sharp front-facing edges
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
		glDisable(GL_LIGHTING)
		glDisable(GL_CULL_FACE)
		glLineWidth(1)
		glColor3f(r, g, b)
		self.model.draw()
		# Front-facing edge glow
		glLineWidth(self.EDGE_GLOW_WIDTH // 2 + 1)
		glColor4f(r, g, b, self.EDGE_GLOW_ALPHA * 2.0) 
		self.model.draw()
		glLineWidth(self.EDGE_GLOW_WIDTH)
		glColor4f(r, g, b, self.EDGE_GLOW_ALPHA) 
		self.model.draw()
		# Back-facing edge lines
		glDisable(GL_DEPTH_TEST)
		glLineWidth(self.BACK_EDGE_WIDTH)
		self.model.draw()
		glPopAttrib()

